import {
	IParam,
	IHttpResponse,
	ICalendarControllerParams,
	ICtrlActionResult,
} from '@/core/interface';
import { ICalendarAbility } from '@/core/interface/widgets/ability';
import { ICalendarController } from '@/core/interface/widgets/controller';
import { CalendarActionType } from '@/core/interface/widgets/event';
import { ICalendarStore } from '@/core/interface/widgets/store';
import { ControlVOBase } from '@/core/modules';
import CalendarService from '@/core/modules/ctrl-service/calendar-service';
import { dateFormat, deepCopy } from '@/core/utils';
import moment from 'moment';
import { MDCtrlController } from './md-ctrl-controller';

/**
 * 日历控制器
 *
 * @export
 * @class CalendarController
 * @extends {(MDCtrlController<A | CalendarEventActionType, ICalendarStore>)}
 * @implements {ICalendarController<T>}
 * @template A
 */
export class CalendarController
	extends MDCtrlController<CalendarActionType, ICalendarStore, ICalendarAbility>
	implements ICalendarController<ICalendarStore, ICalendarAbility>
{
	/**
	 * Creates an instance of CalendarController.
	 * @param {ICalendarControllerParams} params
	 * @memberof CalendarController
	 */
	public constructor(
		params: ICalendarControllerParams<CalendarActionType, ICalendarAbility>
	) {
		super(params);
		this.ctrlInit(params);
	}

	/**
	 * 日历部件服务
	 *
	 * @protected
	 * @type {CalendarService<ControlVOBase[]>}
	 * @memberof CalendarController
	 */
	protected declare ctrlService: CalendarService<ControlVOBase[]>;

	/**
	 * 备份日历项上下文菜单
	 *
	 * @memberof CalendarController
	 */
	public copyActionModel: IParam = {};

	/**
	 * 事件类型map
	 *
	 * @memberof CalendarController
	 */
	public eventKey: Map<string, string> = new Map();

	/**
	 * 是否已经选中第一条数据
	 *
	 * @type {boolean}
	 * @memberof CalendarController
	 */
	public isSelectFirst: boolean = false;

	/**
	 * 处理部件初始化
	 *
	 * @protected
	 * @param { ICalendarControllerParams<CalendarActionType, ICalendarAbility>} params
	 * @memberof CalendarController
	 */
	protected processCtrlInit(
		params: ICalendarControllerParams<CalendarActionType, ICalendarAbility>
	) {
		super.processCtrlInit(params);
		Object.assign(this.store, {
			isNoData: false,
			quickToolbarItems: [],
			events: [],
			calendarType: '',
			defaultView: 'dayGridMonth',
		});
		// TODO 初始化上下文菜单
		// this.initActionModel();
		// TODO 初始化快速工具栏
		// this.initQuickToolbar();
		// 初始化事件map对象
		this.initEventKey();
		this.store.calendarType = this.model.calendarStyle;
		if (Object.is(this.store.calendarType, 'WEEK')) {
			this.store.defaultView = 'timeGridWeek';
		} else if (Object.is(this.store.calendarType, 'DAY')) {
			this.store.defaultView = 'timeGridDay';
		}
	}

	/**
	 * 初始化事件map对象
	 *
	 * @memberof CalendarController
	 */
	public initEventKey() {
		this.eventKey = new Map();
		const calendarItems = this.model.calendarItems;
		if (calendarItems.length > 0) {
			calendarItems.forEach((calendarItem: IParam) => {
				this.eventKey.set(
					calendarItem.itemType,
					calendarItem?.entityKeyName?.toLowerCase()
				);
			});
		}
	}

	/**
	 * 日历数据加载
	 *
	 * @param {IParam} [opts={}]
	 * @param {boolean} [pageReset=false]
	 * @return {*}  {Promise<IHttpResponse>}
	 * @memberof ChartController
	 */
	public async load(opts: IParam = {}): Promise<ICtrlActionResult> {
		const { context } = this.store;
		const { fetchAction } = this.actions;
		if (!fetchAction) {
			console.warn(App.ts('widget.md.notconfig.fetchaction', '未配置加载行为'));
			return Promise.reject({ ok: false, data: this.getData(), rowData: null });
		}
		const { limit, noSort, sortDir, sortField } = this.model;
		// 处理请求参数
		const calendarArgs = opts.arg;
		let start =
			calendarArgs && calendarArgs.start
				? dateFormat(calendarArgs.start)
				: null;
		let end =
			calendarArgs && calendarArgs.end ? dateFormat(calendarArgs.end) : null;
		let arg = { start: start, end: end };
		if (opts && opts.query) {
			Object.assign(arg, { query: opts.query });
		}
		const page: any = {};
		//  开启分页
		Object.assign(page, { page: 0, size: limit || 1000 });
		//  排序
		if (!noSort && sortField) {
			Object.assign(page, {
				sort: `${sortField},${sortDir ? sortDir : 'asc'}`,
			});
		}
		Object.assign(arg, page);
		const parentData: IParam = {};
		this.emit('beforeLoad', [parentData]);
		Object.assign(arg, parentData);
		const tempViewParams: IParam = parentData.viewParams
			? parentData.viewParams
			: {};
		Object.assign(arg, { viewParams: tempViewParams });
		const tempContext = deepCopy(context);
		this.beforeAsyncAction('load', tempContext, arg);
		try {
			const response: IHttpResponse = await this.ctrlService.search(
				fetchAction,
				tempContext,
				arg
			);
			if (!response || !response.success) {
				this.afterAsyncAction('load', response);
				return Promise.reject({
					ok: false,
					data: this.getData(),
					rowData: response,
				});
			}
			this.store.data = response.data;
			this.store.events = this.store.data;
			if (this.selectFirstDefault) {
				this.isSelectFirst = true;
			}
			this.scheduleSort();
			this.afterAsyncAction('load', response);
			return Promise.resolve({
				ok: true,
				data: this.getData(),
				rowData: response,
			});
		} catch (error: any) {
			this.afterAsyncAction('load', error);
			if (error) {
				return error;
			} else {
				return Promise.reject({
					ok: false,
					data: this.getData(),
					rowData: error,
				});
			}
		}
	}

	/**
	 * 日程排序
	 *
	 * @memberof CalendarController
	 */
	public scheduleSort() {
		if (
			Object.is(this.store.calendarType, 'TIMELINE') &&
			this.store.events.length > 0
		) {
			this.store.events.sort((a: any, b: any) => {
				const x: any = a.start;
				const y: any = b.start;
				return moment(x).isAfter(y) ? -1 : moment(x).isBefore(y) ? 1 : 0;
			});
			// 默认选中第一项
			if (this.selectFirstDefault) {
				this.onTimeLineClick(this.store.events[0]);
			}
		}
	}

	/**
	 * 时间轴点击事件
	 *
	 * @param {*} item 项数据
	 * @memberof CalendarController
	 */
	public onTimeLineClick(item: any) {
		this.store.events.forEach((event: any) => {
			event.srfchecked = 0;
		});
		item.srfchecked = Number(!item.srfchecked);
		this.onEventClick(item, true);
	}

	/**
	 * 日程点击事件
	 *
	 * @param {*} arg calendar事件对象或event数据
	 * @param {*} isOriginData true：$event是原始event数据，false：是组件
	 * @memberof CalendarController
	 */
	public onEventClick(arg: IParam, isOriginData: boolean = false) {
		let event: any = {};
		if (isOriginData) {
			event = arg;
		} else {
			let data = arg.$DO;
			let calendarItem = this.model.calendarItems.find((_item: IParam) => {
				return _item.itemType == data.itemType;
			});
			event = Object.assign(
				{
					title: arg.title,
					start: arg.start,
					end: arg.end,
					srfkey: data[calendarItem.entityKeyName?.toLowerCase()],
				},
				data
			);
		}
		this.store.selections = [event];
		this.emit('selectionChange', this.store.selections);
	}

	/**
	 * 获取事件key
	 *
	 * @param {*} event 事件对象
	 * @return {*}
	 * @memberof CalendarControlBase
	 */
	public getEventKey(event: any) {
		if (event?.itemType && this.eventKey.has(event.itemType)) {
			return this.eventKey.get(event.itemType);
		}
		return '';
	}

	/**
	 * 部件挂载
	 *
	 * @memberof CalendarController
	 */
	public ctrlMounted(): void {
		super.ctrlMounted();
	}

	/**
	 * 获取部件能力
	 *
	 * @return {*}  {A}
	 * @memberof CalendarController
	 */
	public getAbility(): ICalendarAbility {
		return {
			...super.getAbility(),
		};
	}
}
